import datetime
import functools
import logging
import pandas as pd

from absl import app
from tornado.ioloop import IOLoop, PeriodicCallback

import coin.flow.subscriber as flow_subscriber
from coin.flow.simple_queue import SimpleQueue
from coin.base.datetime_util import to_datetime
from coin.base.timestamp import get_timestamp

from coin.strategy.mm.base.multi_feed_subsystem import MultiFeedSubsystem
from coin.feed.fastfeed.native_wrapper import run_from_feed_cache

import experimental.prophet as prophet
from coin.exchange.okex.kr_rest.product import OkexProduct

from coin.strategy.interval.research import features
from coin.strategy.interval.model import LinearModel
from coin.strategy.interval.profile.taekwon import greats, merge_greats


class Test:
  def __init__(self):
    self._vars = []
    self._var_names = []
    self._live_begin_ts = None
    self._model = LinearModel.load(
        'coin/strategy/interval/model/ridge_fit_taekwon_bitflyer_model.pkl')
    self._products = [
        'bitflyer-fxbtcjpy', 'bitmex-xbtusd', 'okex-btcusd-quarter', 'okex-btcusd-perpetual'
    ]

  def on_eval(self, graph, live=False):
    ts = graph.get_named_variable('global_timestamp').value
    if live and ts < self._live_begin_ts:
      return

    if not (live or ts % 10**9 == 0):
      return

    row = pd.Series({var.name: float(var.value or 0.0) for var in self._vars})
    pos = self._model.eval(row)

    print("Time: %s, Position: %f" % (to_datetime(ts), pos))

  def run_from_fastfeed(self):
    graph = prophet.Graph()
    with prophet.as_default_graph(graph):
      self._vars = features.features(self._products, datetime.date(
          2019, 8, 1)) + [prophet.global_timestamp()]
      self._var_names = [var.name for var in self._vars]

    machine = 'feed-01.ap-northeast-1.aws'
    adapter = prophet.FastfeedGraphAdapter(graph, machine, eval_callback=self.on_eval)
    feed_sub_req = adapter.get_feed_sub_requests()

    run_from_feed_cache(feed_sub_req,
                        adapter.on_book_reset,
                        datetime.date(2019, 8, 1),
                        datetime.datetime(2019, 8, 1, 2),
                        machine=machine)

  def run_live(self):
    ioloop = IOLoop.current()
    queue = SimpleQueue('queue')
    flow_sub = flow_subscriber.from_queue(queue)

    graph = prophet.Graph()
    with prophet.as_default_graph(graph):
      self._vars = features.features(self._products,
                                     datetime.datetime.now()) + [prophet.global_timestamp()]
      self._var_names = [var.name for var in self._vars]

    adapter = prophet.FastfeedGraphAdapter(graph, '')
    feed_sub_req = adapter.get_feed_sub_requests()

    feed_subsystem = MultiFeedSubsystem()
    feed_subsystem.subscribe_fastfeed(feed_sub_req, adapter.on_book_reset)
    feed_subsystem.start(ioloop, queue, flow_sub)

    interval_trigger = PeriodicCallback(functools.partial(self.on_eval, graph, True), 1000)
    interval_trigger.start()
    self._live_begin_ts = get_timestamp()

    try:
      ioloop.start()
      return 0
    except KeyboardInterrupt:
      return 1


def main(argv):
  tester = Test()

  if len(argv) == 1:
    tester.run_live()
  elif argv[1] == 'live':
    tester.run_live()
  elif argv[1] == 'archive':
    tester.run_from_fastfeed()
  elif argv[1] == 'dump':
    tester.dump_matrix()


if __name__ == '__main__':
  logging.basicConfig(level='DEBUG')
  app.run(main)
